🧠 this, bind, call, apply 완전 정리
this는 함수가 어떻게 호출되었는지에 따라 결정되는 값입니다.
1️⃣ this란?
함수가 실행될 때 결정되는 실행 컨텍스트 객체
🔹 객체의 메서드로 호출될 때
const user = {
name: "Jun",
greet() {
console.log(this.name);
}
};
user.greet(); // Jun
✔️ this → user 객체
🔹 일반 함수 호출
function greet() {
console.log(this);
}
greet();
- 브라우저:
window - strict mode:
undefined
📌 일반 함수는 호출 주체가 없기 때문에 전역 객체를 가리킴
🔹 화살표 함수의 this
const user = {
name: "Jun",
greet: () => {
console.log(this.name);
}
};
user.greet(); // undefined
❗ 화살표 함수는 자기 자신의 this가 없음
→ 상위 스코프의 this를 그대로 사용(lexical this)
2️⃣ bind() - this를 고정하는 방법
this가 고정된 새로운 함수를 반환
function greet() {
console.log(this.name);
}
const user = { name: "Jun" };
const boundGreet = greet.bind(user);
boundGreet(); // Jun
🔹 문법
const newFunc = func.bind(thisArg, arg1, arg2...)
✔️ 실행 ❌
✔️ 새로운 함수 반환
✔️ this 영구 고정
3️⃣ apply() - 배열로 인자 전달
function introduce(age, job) {
console.log(this.name, age, job);
}
const user = { name: "Jun" };
introduce.apply(user, [28, "developer"]);
🔹 문법
func.apply(thisArg, [argsArray])
✔️ 즉시 실행 ❌
✔️ 새로운 함수 반환
✔️ this를 영구적으로 고정
4️⃣ call() - 즉시 실행 버전
bind와 다르게 즉시 실행
function greet() {
console.log(this.name);
}
const user = { name: "Jun" };
greet.call(user); // Jun
🔹 문법
func.call(thisArg, arg1, arg2, ...)
✔️ 실행 즉시 호출
✔️ this를 원하는 객체로 지정 가능
5️⃣ 왜 필요한가?
🔹 콜백에서 this가 깨지는 문제
class Counter {
constructor() {
this.count = 0;
}
increase() {
console.log(++this.count);
}
}
const counter = new Counter();
setTimeout(counter.increase, 1000); // ❌ this 깨짐
setTimeout이 함수를 일반 함수로 호출- 호출 주체가 사라짐
this가 undefined (strict mode)
🔹 해결
setTimeout(counter.increase.bind(counter), 1000);
✔️ this를 counter로 고정
6️⃣ 한눈에 비교
| 메서드 | 실행 여부 | this 지정 | 인자 방식 |
|---|---|---|---|
| bind | 실행 안 함 | 가능 | 개별 전달 |
| apply | 즉시 실행 | 가능 | 배열 전달 |
| call | 즉시 실행 | 가능 | 개별 전달 |
7️⃣ 언제 쓰면 좋을까?
- 다른 객체의 메서드를 빌려 쓸 때
- 콜백에서 this 유지가 필요할 때
- 클래스 메서드를 이벤트 핸들러로 넘길 때
- 함수형 패턴에서 컨텍스트 고정이 필요할